from django.shortcuts import render
from django.db.models import Q
from django.utils import timezone
from django.conf import settings
from rest_framework import viewsets, status, mixins
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.views import APIView
from rest_framework.authtoken.models import Token
from rest_framework.exceptions import ValidationError
import requests
import json
import logging
import os
from django.http import FileResponse, HttpResponse
from .models import User, FoodCategory, Food, FoodImage, FoodSpec, CartItem, Order, OrderItem, Address
from .serializers import (UserSerializer, CategorySerializer, CategoryWithFoodsSerializer, 
                         SimpleFoodSerializer, FoodDetailSerializer, CartItemSerializer, 
                         AddressSerializer, OrderSerializer, OrderCreateSerializer)
from django.db import transaction

# 配置日志器
logger = logging.getLogger(__name__)

class WeChatLoginView(APIView):
    """微信登录视图"""
    permission_classes = [AllowAny]
    
    def post(self, request):
        logger.info("接收登录请求: %s", request.data)
        
        # 获取小程序传来的code和用户信息
        code = request.data.get('code')
        user_info = request.data.get('userInfo')
        
        # 获取前端传递的身份标识符
        stored_openid = request.data.get('stored_openid')
        
        # 获取前端传递的用户资料
        nickname = request.data.get('nickname')
        avatar_url = request.data.get('avatar_url')
        
        if not code:
            logger.error("缺少必要参数code: %s", request.data)
            return Response({'error': '缺少必要参数code'}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            # 获取用户提供的资料
            if user_info:
                # 优先使用用户资料中的昵称和头像
                nickname = user_info.get('nickName') or nickname
                avatar_url = user_info.get('avatarUrl') or avatar_url
            
            logger.info("处理用户资料: nickname=%s, avatar_url_length=%s", 
                       nickname, len(avatar_url) if avatar_url else 0)
            
            # 从微信API获取openid
            openid = None
            
            # 模拟环境下，使用固定openid
            if code.startswith("the code is a mock") or code == "mock":
                # 模拟环境，使用固定的openid
                openid = "mock_openid_stable"
                logger.info("模拟环境，使用固定openid: %s", openid)
            else:
                # 真实环境，调用微信API获取openid
                if stored_openid:
                    # 如果前端已经存储了openid，优先使用它
                    openid = stored_openid
                    logger.info("使用前端存储的openid: %s", openid)
                else:
                    # 调用微信API获取openid
                    wx_resp = self.get_openid_from_wechat(code)
                    if wx_resp and 'openid' in wx_resp:
                        openid = wx_resp['openid']
                        logger.info("从微信API获取到openid: %s", openid)
                    else:
                        # 如果API请求失败，记录错误并返回错误响应
                        error_msg = wx_resp.get('errmsg', '未知错误') if wx_resp else '无法获取openid'
                        logger.error("微信API返回错误: %s", error_msg)
                        return Response({
                            'error': f'微信授权失败: {error_msg}', 
                            'wx_response': wx_resp
                        }, status=status.HTTP_400_BAD_REQUEST)
            
            if not openid:
                logger.error("无法确定用户标识")
                return Response({'error': '无法确定用户标识'}, status=status.HTTP_400_BAD_REQUEST)
            
            # 查询是否有匹配此openid的用户
            user = None
            try:
                user = User.objects.get(openid=openid)
                logger.info("找到匹配的用户: id=%s, username=%s", user.id, user.username)
            except User.DoesNotExist:
                logger.info("未找到匹配openid的用户，将创建新用户")
                
                # 确定用户名，优先使用微信昵称，确保唯一性
                username = None
                if nickname:
                    base_username = nickname
                    username = base_username
                    counter = 1
                    
                    # 确保用户名唯一
                    while User.objects.filter(username=username).exists():
                        username = f"{base_username}_{counter}"
                        counter += 1
                    
                    logger.info("为新用户生成唯一用户名: %s", username)
                else:
                    # 如果没有昵称，使用openid的一部分作为用户名
                    username = f"wx_user_{openid[-8:]}"
                    counter = 1
                    
                    # 确保用户名唯一
                    while User.objects.filter(username=username).exists():
                        username = f"wx_user_{openid[-8:]}_{counter}"
                        counter += 1
                
                # 创建新用户
                try:
                    user = User.objects.create_user(
                        username=username,
                        password=None,  # 微信登录不需要密码
                        first_name=nickname or '',
                        role='customer'  # 默认设置为普通客户
                    )
                    user.openid = openid
                    user.save()
                    logger.info("创建新用户成功: id=%s, username=%s, openid=%s", user.id, user.username, openid)
                except Exception as e:
                    import traceback
                    logger.error("创建用户失败: %s\n%s", str(e), traceback.format_exc())
                    
                    # 尝试使用完全随机用户名
                    import uuid
                    random_username = f"wx_user_{uuid.uuid4().hex[:10]}"
                    user = User.objects.create_user(
                        username=random_username,
                        password=None,
                        first_name=nickname or '',
                        role='customer'
                    )
                    user.openid = openid
                    user.save()
                    logger.info("使用随机用户名创建成功: id=%s, username=%s", user.id, user.username)
            
            # 更新用户信息 - 头像和昵称
            need_update = False
            
            try:
                # 只有有新值时才更新头像
                if avatar_url and (not user.avatar or user.avatar != avatar_url):
                    user.avatar = avatar_url
                    need_update = True
                    logger.info("更新用户头像")
                
                # 只有在有新昵称且用户没有昵称或昵称为空时更新昵称
                if nickname and (not user.first_name or user.first_name.strip() == ''):
                    user.first_name = nickname
                    need_update = True
                    logger.info("更新用户昵称: %s", nickname)
                
                # 更新最后登录时间
                user.last_login = timezone.now()
                need_update = True
                
                if need_update:
                    try:
                        user.save()
                        logger.info("更新用户信息成功")
                    except Exception as e:
                        logger.error("更新用户信息失败: %s", str(e))
                        # 出错时不阻止登录过程继续
            except Exception as e:
                logger.error("处理用户信息更新时出错: %s", str(e))
                # 出错时不阻止登录过程继续
            
            # 创建或获取Token
            token, created = Token.objects.get_or_create(user=user)
            if created:
                logger.info("创建新token")
            else:
                logger.info("使用现有token")
            
            # 构建返回数据
            user_data = {
                'id': user.id,
                'username': user.username,
                'nickname': user.first_name or user.username,
                'avatar': user.avatar,
                'openid': user.openid,
                'is_staff': user.is_staff
            }
            
            logger.info("登录成功，用户ID: %s, openid: %s", user.id, openid)
            return Response({
                'token': token.key,
                'user': user_data
            })
            
        except Exception as e:
            import traceback
            logger.error("登录处理失败: %s\n%s", str(e), traceback.format_exc())
            return Response({'error': f'登录处理失败: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    
    def get_openid_from_wechat(self, code):
        """
        调用微信API获取openid
        """
        try:
            # 获取微信小程序配置
            appid = settings.WX_MINIAPP['APPID']
            secret = settings.WX_MINIAPP['SECRET']
            
            # 请求微信API
            url = 'https://api.weixin.qq.com/sns/jscode2session'
            params = {
                'appid': appid,
                'secret': secret,
                'js_code': code,
                'grant_type': 'authorization_code'
            }
            
            logger.info("请求微信API获取openid，参数: %s", params)
            
            # 发送请求到微信服务器
            response = requests.get(url, params=params)
            result = response.json()
            
            logger.info("微信API响应: %s", result)
            
            # 检查是否成功获取openid
            if 'openid' not in result:
                logger.error("微信API返回错误: %s", result.get('errmsg', '未知错误'))
            
            return result
        except Exception as e:
            import traceback
            logger.error("调用微信API获取openid失败: %s\n%s", str(e), traceback.format_exc())
            return None


class CategoryViewSet(viewsets.ReadOnlyModelViewSet):
    """食品分类视图集"""
    queryset = FoodCategory.objects.filter(is_active=True)
    serializer_class = CategorySerializer
    permission_classes = [AllowAny]
    
    def get_serializer_class(self):
        if self.action == 'retrieve' and self.request.query_params.get('include_foods', 'false').lower() == 'true':
            return CategoryWithFoodsSerializer
        return self.serializer_class
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        return context
    
    def retrieve(self, request, *args, **kwargs):
        try:
            print(f"正在获取分类详情，参数: {kwargs}, 查询参数: {request.query_params}")
            
            instance = self.get_object()
            include_foods = request.query_params.get('include_foods', 'false').lower() == 'true'
            
            serializer_class = self.get_serializer_class()
            print(f"获取到分类: {instance.name}, 序列化器: {serializer_class.__name__}, include_foods: {include_foods}")
            
            # 如果需要包含食品列表并且使用的是CategoryWithFoodsSerializer
            if include_foods and serializer_class == CategoryWithFoodsSerializer:
                # 获取食品列表
                foods = Food.objects.filter(category=instance, is_active=True)
                print(f"获取到食品列表，共 {foods.count()} 项")
                
                # 直接通过序列化器上下文传递foods数据，而不是修改实例
                serializer = serializer_class(
                    instance, 
                    context={
                        'request': request,
                        'foods': foods
                    }
                )
            else:
                serializer = serializer_class(instance, context={'request': request})
            
            data = serializer.data
            print(f"序列化成功，返回数据长度: {len(str(data))}")
            
            return Response(data)
        except Exception as e:
            import traceback
            print(f"处理分类详情时出错: {str(e)}")
            print(traceback.format_exc())
            raise


class FoodViewSet(viewsets.ReadOnlyModelViewSet):
    """食品视图集"""
    queryset = Food.objects.filter(is_active=True)
    permission_classes = [AllowAny]
    
    def get_serializer_class(self):
        if self.action == 'retrieve':
            return FoodDetailSerializer
        return SimpleFoodSerializer
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        return context
    
    def get_queryset(self):
        queryset = Food.objects.filter(is_active=True)
        
        # 分类筛选
        category_id = self.request.query_params.get('category')
        if category_id:
            queryset = queryset.filter(category_id=category_id)
        
        # 热销筛选
        is_hot = self.request.query_params.get('is_hot')
        if is_hot and is_hot.lower() == 'true':
            queryset = queryset.filter(is_hot=True)
        
        # 新品筛选
        is_new = self.request.query_params.get('is_new')
        if is_new and is_new.lower() == 'true':
            queryset = queryset.filter(is_new=True)
        
        # 搜索
        keyword = self.request.query_params.get('keyword')
        if keyword:
            queryset = queryset.filter(
                Q(name__icontains=keyword) | 
                Q(description__icontains=keyword)
            )
        
        return queryset


class CartItemViewSet(viewsets.ModelViewSet):
    """购物车视图集"""
    serializer_class = CartItemSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        return CartItem.objects.filter(user=self.request.user)
    
    def create(self, request, *args, **kwargs):
        """创建购物车项，覆盖默认create以处理已存在项的更新"""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        # 检查是否是已存在项的更新
        food_id = request.data.get('food')
        spec_id = request.data.get('spec')
        
        # 检查是否已在购物车中
        existing = None
        if food_id:
            query = {
                'user': request.user,
                'food_id': food_id
            }
            if spec_id:
                query['spec_id'] = spec_id
            else:
                query['spec'] = None
                
            existing = CartItem.objects.filter(**query).first()
        
        # 调用perform_create来处理
        self.perform_create(serializer)
        
        # 如果是更新已有项，返回更新后的项
        if existing:
            serializer = self.get_serializer(instance=existing)
        
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
        
    def perform_create(self, serializer):
        """创建购物车项或更新已有项的数量"""
        # 检查食品是否存在
        food_id = self.request.data.get('food')
        try:
            food = Food.objects.get(id=food_id, is_active=True)
        except Food.DoesNotExist:
            raise ValidationError('食品不存在或已下架')
        
        # 检查规格是否存在
        spec_id = self.request.data.get('spec')
        spec = None
        if spec_id:
            try:
                spec = FoodSpec.objects.get(id=spec_id, food=food)
            except FoodSpec.DoesNotExist:
                raise ValidationError('规格不存在')
        
        try:
            # 检查是否已在购物车中
            existing = CartItem.objects.filter(
                user=self.request.user,
                food=food,
                spec=spec
            ).first()
            
            if existing:
                # 如果已存在，增加数量
                count_to_add = int(self.request.data.get('count', 1))
                existing.count += count_to_add
                existing.save()
                
                # 这里不需要返回值，perform_create方法不直接参与响应生成
                # create方法会处理响应
            else:
                # 如果不存在，创建新项
                serializer.save(user=self.request.user)
        except Exception as e:
            import traceback
            print(f"购物车添加/更新失败: {str(e)}")
            print(traceback.format_exc())
            raise
    
    @action(detail=False, methods=['post'])
    def batch_update(self, request):
        """批量更新购物车项选中状态"""
        is_checked = request.data.get('is_checked')
        ids = request.data.get('ids')
        
        if is_checked is None or ids is None:
            return Response({'error': '缺少参数'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 更新指定的购物车项
        CartItem.objects.filter(id__in=ids, user=request.user).update(is_checked=is_checked)
        
        return Response({'success': True})
    
    @action(detail=False, methods=['get'])
    def summary(self, request):
        """购物车汇总信息"""
        cart_items = self.get_queryset().filter(is_checked=True)
        total_count = sum(item.count for item in cart_items)
        total_price = sum(item.total_price for item in cart_items)
        
        return Response({
            'total_count': total_count,
            'total_price': total_price
        })


class AddressViewSet(viewsets.ModelViewSet):
    """收货地址视图集"""
    serializer_class = AddressSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        return Address.objects.filter(user=self.request.user)
    
    def perform_create(self, serializer):
        serializer.save(user=self.request.user)


class OrderViewSet(viewsets.GenericViewSet, 
                  mixins.CreateModelMixin,
                  mixins.ListModelMixin,
                  mixins.RetrieveModelMixin):
    """订单视图集"""
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        return Order.objects.filter(user=self.request.user)
    
    def get_serializer_class(self):
        if self.action == 'create':
            return OrderCreateSerializer
        return OrderSerializer
    
    def get_serializer_context(self):
        context = super().get_serializer_context()
        return context
    
    def list(self, request, *args, **kwargs):
        # 根据状态筛选订单
        status_param = request.query_params.get('status')
        queryset = self.get_queryset()
        
        if status_param:
            # 支持多状态查询，例如 "2,3"
            if ',' in status_param:
                # 分割并转换为整数列表
                status_values = [int(s.strip()) for s in status_param.split(',') if s.strip().isdigit()]
                if status_values:
                    queryset = queryset.filter(status__in=status_values)
            # 单一状态查询
            elif status_param.isdigit() and int(status_param) in [1, 2, 3, 4, 5, 6]:
                queryset = queryset.filter(status=int(status_param))
        
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)
    
    @action(detail=True, methods=['post'])
    def cancel(self, request, pk=None):
        """取消订单"""
        order = self.get_object()
        success = order.cancel()
        
        if success:
            return Response({'success': True})
        return Response(
            {'error': '只有待付款的订单可以取消'}, 
            status=status.HTTP_400_BAD_REQUEST
        )
    
    @action(detail=True, methods=['post'])
    def pay(self, request, pk=None):
        """支付订单（模拟）"""
        order = self.get_object()
        
        if order.status != 1:
            return Response(
                {'error': '只有待付款的订单可以支付'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 更新订单状态
        order.status = 2  # 待发货
        order.paid_at = timezone.now()
        order.save()
        
        return Response({'success': True})
    
    @action(detail=True, methods=['post'])
    def deliver(self, request, pk=None):
        """发货（模拟）"""
        order = self.get_object()
        
        if order.status != 2:
            return Response(
                {'error': '只有待发货的订单可以发货'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 更新订单状态
        order.status = 3  # 待收货
        order.delivered_at = timezone.now()
        order.save()
        
        return Response({'success': True})
    
    @action(detail=True, methods=['post'])
    def receive(self, request, pk=None):
        """确认收货"""
        order = self.get_object()
        
        if order.status != 3:
            return Response(
                {'error': '只有待收货的订单可以确认收货'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 更新订单状态
        order.status = 4  # 待评价
        order.received_at = timezone.now()
        order.save()
        
        return Response({'success': True})
    
    @action(detail=True, methods=['post'])
    def complete(self, request, pk=None):
        """完成订单（评价后）"""
        order = self.get_object()
        
        if order.status != 4:
            return Response(
                {'error': '只有待评价的订单可以完成'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # 更新订单状态
        order.status = 5  # 已完成
        order.finished_at = timezone.now()
        order.save()
        
        return Response({'success': True})

    @action(detail=False, methods=['post'], url_path='update-food-sold')
    def update_food_sold(self, request):
        """
        更新所有已完成订单中的食品销量
        """
        if not request.user.is_staff:
            return Response({"detail": "只有管理员才能执行此操作"}, status=status.HTTP_403_FORBIDDEN)
            
        logger = logging.getLogger('api')
        logger.info(f"管理员 {request.user.username} 开始更新食品销量")
        
        # 重置所有食品的销量为0
        try:
            with transaction.atomic():
                from .models import Food
                Food.objects.all().update(sold=0)
                logger.info("已重置所有食品销量为0")
                
                # 获取所有已完成的订单
                completed_orders = self.get_queryset().filter(status='completed')
                logger.info(f"找到 {completed_orders.count()} 个已完成订单")
                
                # 创建一个字典来累计每个食品的销量
                food_sold_count = {}
                
                # 遍历所有已完成订单的订单项
                for order in completed_orders:
                    order_items = order.items.all()
                    
                    for item in order_items:
                        food_id = item.food.id
                        count = item.count
                        
                        if food_id in food_sold_count:
                            food_sold_count[food_id] += count
                        else:
                            food_sold_count[food_id] = count
                
                # 更新食品销量
                for food_id, sold_count in food_sold_count.items():
                    food = Food.objects.get(id=food_id)
                    food.sold = sold_count
                    food.save()
                    logger.info(f"更新食品 {food.name}(ID:{food_id}) 销量为 {sold_count}")
                
                return Response({
                    "detail": f"成功更新 {len(food_sold_count)} 个食品的销量",
                    "updated_foods_count": len(food_sold_count),
                    "orders_processed": completed_orders.count()
                })
        except Exception as e:
            logger.error(f"更新食品销量失败: {str(e)}")
            return Response({"detail": f"更新食品销量失败: {str(e)}"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class HomeDataView(APIView):
    """首页数据视图"""
    permission_classes = [AllowAny]
    
    def get(self, request):
        # 获取轮播图（使用新品作为轮播图）
        banners = Food.objects.filter(is_new=True, is_active=True)[:3]
        
        # 获取分类
        categories = FoodCategory.objects.filter(is_active=True)[:5]
        
        # 获取热销商品
        hot_items = Food.objects.filter(is_hot=True, is_active=True)[:4]
        
        # 创建序列化上下文
        context = {'request': request}
        
        return Response({
            'banners': SimpleFoodSerializer(banners, many=True, context=context).data,
            'categories': CategorySerializer(categories, many=True, context=context).data,
            'hot_items': SimpleFoodSerializer(hot_items, many=True, context=context).data
        })


class AgreementView(APIView):
    """用户协议和隐私政策视图"""
    permission_classes = [AllowAny]
    
    def get(self, request, document_type):
        """
        获取用户协议或隐私政策文档
        document_type: 'user_agreement' 或 'privacy_policy'
        """
        valid_types = {
            'user_agreement': 'user_agreement.html',
            'privacy_policy': 'privacy_policy.html'
        }
        
        if document_type not in valid_types:
            return Response({'error': '无效的文档类型'}, status=status.HTTP_400_BAD_REQUEST)
        
        file_name = valid_types[document_type]
        file_path = os.path.join(settings.STATIC_ROOT, 'agreements', file_name)
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            return HttpResponse(content, content_type='text/html; charset=utf-8')
        except FileNotFoundError:
            return Response({'error': '文档不存在'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'error': f'获取文档失败: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
